home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 211_01 / xmerger.c < prev    next >
Text File  |  1980-01-01  |  12KB  |  652 lines

  1. /* XMERGER.C   VERS:- 01.00  DATE:- 09/26/86  TIME:- 09:37:42 PM */
  2. /*
  3. %CC1 $1.C -O -X -E6000
  4. %CLINK $1 DIO -F CHARFUN STRFUN -S -E6000
  5. %DELETE $1.CRL 
  6. */
  7. /* 
  8. Description:
  9.  
  10. Merge two sorted files, with output redirection.
  11.  
  12. The files must be sorted on the same key used in the merge.
  13. The key can be a sequence of digit fields.
  14. The key length can be specified.
  15. The key start can be defined by a string each record is searched for.
  16.  
  17. Records can be of variable length, defined by a delimiter string,
  18. eg "\n" if each line is a record.
  19. Records can be multiline.
  20.  
  21. Various options:  see help_mess() for summary.
  22. For usage:  see help_mess().
  23.  
  24.  
  25. The logic is adapted from that of MERGE, from the Van Nuys Toolkit, 
  26. by Eugene H. Mallory.
  27. The function decode() is adapted from code in SEARCH, from the
  28. Van Nuys Toolkit.
  29.  
  30.  
  31. By J.A. Rupley, Tucson, Arizona
  32. Coded for BDS C compiler, version 1.50a
  33. */
  34.  
  35. #include "BDSCIO.H"
  36. #include "DIO.H"
  37.  
  38. #define BUFLEN     60*128
  39.  
  40. FILE fcb;
  41. char buf1[BUFLEN], buf2[BUFLEN], *s1, *s2;
  42. char delim[MAXLINE], pattern[MAXLINE];
  43. char digits1[MAXLINE], digits2[MAXLINE];
  44. char filename[20];
  45. int flag1, flag2;
  46. int xi, xj;
  47. int flag;
  48. int upper_case, reverse, column, length, file_only, input_only, duplicate;
  49. int merge, num_only, reject, title, unique;
  50. int optionerr;
  51.  
  52. main(argc, argv)
  53. char **argv;
  54. int argc;
  55.  
  56. {
  57.     dioinit(&argc, argv);
  58.  
  59.     flag = flag1 = flag2 = 0;
  60.  
  61.     /*for standard merge*/
  62.     /*
  63.         column = length = 0;
  64.         merge = 1;
  65.         upper_case = 0;
  66.         reverse = 0;
  67.         unique = 0;
  68.         num_only = 0;
  69.         reject = 0;
  70.         title = 0;
  71.         strcpy(delim, "\n");
  72.         *pattern = '\0';
  73.     */
  74.  
  75.     /*for CAS files = default setup*/
  76.     column = 0;
  77.     length = 20;
  78.     merge = 0;
  79.     upper_case = 0;
  80.     reverse = 1;
  81.     unique = 1;
  82.     num_only = 1;
  83.     reject = 1;
  84.     title = 3;
  85.     strcpy(delim, "\n\*");
  86.     strcpy(pattern, "AN  CA");
  87.  
  88.     get_options(&argc, argv);
  89.     if (optionerr)
  90.         help_mess();
  91.     if (argc < 2)
  92.     {
  93.         typef("XMERGE: No file name given.\n");
  94.         help_mess();
  95.     }
  96.     if (fopen(argv[1], fcb) == -1)
  97.         error("MERGE: Unable to open file %s.", argv[1]);
  98.     strcpy(filename, argv[1]);
  99.  
  100.     if (length == 0)
  101.         length = BUFLEN;
  102.     if (column > 0)
  103.         column--;
  104.     if (duplicate || file_only || input_only)
  105.         merge = unique = 0;
  106.     if (unique)
  107.         merge = input_only = file_only = duplicate = 0;
  108.     if (merge)
  109.         input_only = file_only = duplicate = 0;
  110.     if (!*pattern)
  111.         reject = 0;
  112.  
  113.     getinput();
  114.     getfile();
  115.     while (TRUE)
  116.     {
  117.         flag = string_compare(s1, s2);
  118.         if (flag == 0)
  119.         {
  120.             if (unique || duplicate)
  121.             {
  122.                 putrec(3, buf1);
  123.                 *buf1 = *buf2 = '\0';
  124.                 getinput();
  125.                 getfile();
  126.             }
  127.             else
  128.                 if (merge)
  129.             {
  130.                 putrec(1, buf1);
  131.                 *buf1 = '\0';
  132.                 getinput();
  133.             }
  134.             else
  135.                 if (input_only || file_only)
  136.             {
  137.                 *buf1 = *buf2 = '\0';
  138.                 getinput();
  139.                 getfile();
  140.             }
  141.         }
  142.         else
  143.             if (flag > 0)
  144.         {
  145.             if (unique || merge || file_only)
  146.                 putrec(2, buf2);
  147.             *buf2 = '\0';
  148.             getfile();
  149.         }
  150.         else
  151.             {
  152.             if (unique || merge || input_only)
  153.                 putrec(1, buf1);
  154.             *buf1 = '\0';
  155.             getinput();
  156.         }
  157.     }
  158. }
  159.  
  160.  
  161. void putrec(input, buffer)
  162. int input;
  163. char *buffer;
  164. {
  165.     if (title && *buffer)
  166.     {
  167.         if (*buffer == '\f' || *buffer == '\n')
  168.             while (*buffer == '\f' || *buffer == '\n')
  169.                 putchar(*buffer++);
  170.         else
  171.             putchar('\n');
  172.         if ((title > 1) && (input > 1))
  173.         {
  174.             puts(filename);
  175.             putchar('\n');
  176.         }
  177.         if ((title % 2) && (input % 2))
  178.         {
  179.             puts(_infile);
  180.             putchar('\n');
  181.         }
  182.     }
  183.     while (*buffer)
  184.         putchar(*buffer++);
  185. }
  186.  
  187.  
  188. int bufx_fill(input, sx, bufx, flagx)
  189. char **sx, *bufx;
  190. int input, *flagx;
  191. {
  192.     char *p_delim;
  193.     int c2, c, i;
  194.  
  195. restart :
  196.     *sx = bufx[0] = '\0';
  197.     i = 0;
  198.     p_delim = delim;
  199.  
  200.     while (i < BUFLEN)
  201.     {
  202.         if (*flagx)
  203.             return 0;
  204.         if (input == 2)
  205.         {
  206.             if ((c = getc(fcb)) == '\r')
  207.             {
  208.                 if ((c2 = getc(fcb)) == '\n')
  209.                     c = c2;
  210.                 else
  211.                     ungetc(c2, fcb);
  212.             }
  213.         }
  214.         else
  215.             if (input == 1)
  216.             c = getchar();
  217.         else
  218.             error("XMERGE: wrong input identifier.");
  219.         if ((c == EOF) || (c == CPMEOF))
  220.         {
  221.             *flagx = 1;
  222.             bufx[i] = '\0';
  223.             if (i)
  224.                 strcat(bufx, delim);
  225.             set_sx(input, sx, bufx);
  226.             if (!*sx && reject)
  227.                 goto restart;
  228.             return 1;
  229.         }
  230.         bufx[i++] = c;
  231.         if (c == *p_delim)
  232.         {
  233.             if (!*++p_delim)
  234.             {
  235.                 bufx[i] = '\0';
  236.                 set_sx(input, sx, bufx);
  237.                 if (!*sx && reject)
  238.                     goto restart;
  239.                 return 1;
  240.             }
  241.         }
  242.         else
  243.             p_delim = delim;
  244.     }
  245.     error("XMERGE: record overflows buffer.");
  246. }
  247.  
  248.  
  249. void set_sx(input, sx, bufx)
  250. int input;
  251. char **sx, *bufx;
  252. {
  253.     int temp;
  254.  
  255.     if (strlen(pattern) == 0)
  256.         *sx = bufx;
  257.     else
  258.         if (temp = str1_in_str2(pattern, bufx))
  259.             *sx = bufx + temp;
  260.         else
  261.             *sx = 0;
  262.     return;
  263. }
  264.  
  265.  
  266. void getinput()
  267. {
  268.     if (!bufx_fill(1, &s1, buf1, &flag1))
  269.         inputeof();
  270. }
  271.  
  272.  
  273. void getfile()
  274. {
  275.     if (!bufx_fill(2, &s2, buf2, &flag2))
  276.         fileeof();
  277. }
  278.  
  279.  
  280. void inputeof()
  281. {
  282.     if (unique || merge || file_only)
  283.     {
  284.         do
  285.             {
  286.             putrec(2, buf2);
  287.         }
  288.         while (bufx_fill(2, &s2, buf2, &flag2))
  289.             ;
  290.     }
  291.     dioflush();
  292.     exit();
  293. }
  294.  
  295.  
  296. void fileeof()
  297. {
  298.     fclose(fcb);
  299.     if (unique || merge || input_only)
  300.     {
  301.         do
  302.             {
  303.             putrec(1, buf1);
  304.         }
  305.         while (bufx_fill(1, &s1, buf1, &flag1))
  306.             ;
  307.     }
  308.     dioflush();
  309.     exit();
  310. }
  311.  
  312.  
  313.         /*page eject*/
  314.  
  315. int num_compare(t1, t2)
  316. char *t1, *t2;
  317. {
  318.     int lenx, temp, index1, index2;
  319.  
  320.     lenx = index1 = index2 = 0;
  321.     digits1[0] = digits2[0] = '\0';
  322.  
  323.     if (!*t1 && !*t2)
  324.         return 0;
  325.     else
  326.         if (!*t1)
  327.         return -1;
  328.     else
  329.         if (!*t2)
  330.         return 1;
  331.  
  332.     while (*t1 && (!isdigit(*t1) || (*t1 == '0')))
  333.         t1++;
  334.     while (isdigit(*t1))
  335.     {
  336.         digits1[index1++] = *t1;
  337.         t1++;
  338.     }
  339.  
  340.     while (*t2 && (!isdigit(*t2) || (*t2 == '0')))
  341.         t2++;
  342.     while (isdigit(*t2))
  343.     {
  344.         digits2[index2++] = *t2;
  345.         t2++;
  346.     }
  347.     digits1[index1] = digits2[index2] = '\0';
  348.  
  349.     lenx = ((t1 - s1) > (t2 - s2)) ? (t1 - s1) : (t2 - s2);
  350.     if (temp = (index1 - index2))
  351.         return temp;
  352.     if (temp = strcmp(digits1, digits2))
  353.         return temp;
  354.     if (lenx > (length + column))
  355.         return 0;
  356.     return num_compare(t1, t2);
  357. }
  358.  
  359.  
  360. int string_compare(t1, t2)
  361. char *t1, *t2;
  362. {
  363.     int i;
  364.     if ((strlen(t1) <= column) && (strlen(t2) <= column))
  365.         return 0;
  366.     if (strlen(t1) <= column)
  367.     {
  368.         if (!reverse)
  369.             return -1;
  370.         else
  371.             return 1;
  372.     }
  373.     if (strlen(t2) <= column)
  374.     {
  375.         if (!reverse)
  376.             return 1;
  377.         else
  378.             return -1;
  379.     }
  380.     if (num_only)
  381.     {
  382.         t1 = t1 + column;
  383.         t2 = t2 + column;
  384.         if (!reverse)
  385.             return num_compare(t1, t2);
  386.         else
  387.             return -num_compare(t1, t2);
  388.     }
  389.     if (upper_case)
  390.     {
  391.         for (i = column; i < column + length; i++)
  392.         {
  393.             if (toupper(t1[i]) != toupper(t2[i]))
  394.                 if (!reverse)
  395.                     return toupper(t1[i]) - toupper(t2[i]);
  396.             else
  397.                 return toupper(t2[i]) - toupper(t1[i]);
  398.             if (t1[i] == '\0')
  399.                 return 0;
  400.         }
  401.         return 0;
  402.     }
  403.     else
  404.         {
  405.         for (i = column; i < column + length; i++)
  406.         {
  407.             if (t1[i] != t2[i])
  408.             {
  409.                 if (!reverse)
  410.                     return t1[i] - t2[i];
  411.                 else
  412.                     return t2[i] - t1[i];
  413.             }
  414.             if (t1[i] == '\0')
  415.                 return 0;
  416.         }
  417.         return 0;
  418.     }
  419. }
  420.  
  421.  
  422. /*
  423. the next two functions perform as follows:
  424. if string 1 is found in string2, return the position of the character 
  425. in str2 immediately following the str1 sequence;
  426. else 0 is returned
  427. */
  428.  
  429. int str1_in_str2(str1, str2)
  430. char *str1, *str2;
  431. {
  432.     int i, loc;
  433.  
  434.     for (i = 0; i < strlen(str2); i++)
  435.         if (loc = str1_start_str2(str1, &str2[i]))
  436.             return (loc + i);
  437.     return 0;
  438. }
  439.  
  440.  
  441. int str1_start_str2(str1, str2)
  442. char *str1, *str2;
  443. {
  444.     int loc;
  445.  
  446.     loc = 0;
  447.     while (toupper(*str1++) == toupper(*str2++))
  448.     {
  449.         loc++;
  450.         if (!*str1)
  451.             return loc;
  452.         if (!*str2)
  453.             return 0;
  454.     }
  455.     return 0;
  456. }
  457.  
  458.  
  459. void setuppat(pat, str)
  460. char *pat;
  461. char *str;
  462. {
  463.     int c;
  464.  
  465.     xj = xi = 0;
  466.  
  467.     while (c = pat[xi++])
  468.         decode(c, pat, str, 0);
  469.     str[xj] = 0;
  470.     return;
  471. }
  472.  
  473.  
  474. int decode(c, pat, str, not_flag)
  475. int c, not_flag;
  476. char *pat, *str;
  477. {
  478.     switch (c)
  479.     {
  480.     case '_' :
  481.         str[xj++] = ' ';
  482.         break;
  483.     case '^' :
  484.         c = pat[xi++];
  485.         if (c > 0x7f || c <= 0x40)
  486.             error("SEARCH: illegal ch